package com.sl.ms.carriage.service.impl;

//import cn.hutool.core.collection.CollUtil;
//import cn.hutool.core.stream.StreamUtil;
//import cn.hutool.core.util.ArrayUtil;
//import cn.hutool.core.util.EnumUtil;
//import cn.hutool.core.util.NumberUtil;
//import cn.hutool.core.util.StrUtil;
//import com.alibaba.fastjson.JSON;
//import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
//import com.baomidou.mybatisplus.core.toolkit.Wrappers;
//import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
//import com.sl.ms.base.api.common.AreaFeign;
//import com.sl.ms.carriage.domain.constant.CarriageConstant;
//import com.sl.ms.carriage.domain.dto.CarriageDTO;
//import com.sl.ms.carriage.domain.dto.WaybillDTO;
//import com.sl.ms.carriage.domain.enums.EconomicRegionEnum;
//import com.sl.ms.carriage.entity.CarriageEntity;
//import com.sl.ms.carriage.enums.CarriageExceptionEnum;
//import com.sl.ms.carriage.handler.CarriageChainHandler;
//import com.sl.ms.carriage.mapper.CarriageMapper;
//import com.sl.ms.carriage.service.CarriageService;
//import com.sl.ms.carriage.utils.CarriageUtils;
//import com.sl.transport.common.exception.SLException;
//import com.sl.transport.common.util.ObjectUtil;
//import org.jetbrains.annotations.NotNull;
//import org.springframework.data.redis.core.StringRedisTemplate;
//import org.springframework.stereotype.Service;
//import javax.annotation.Resource;
//import java.math.BigDecimal;
//import java.math.RoundingMode;
//import java.util.Collection;
//import java.util.LinkedHashMap;
//import java.util.List;
//import java.util.stream.Collectors;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.EnumUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sl.ms.base.api.common.AreaFeign;
import com.sl.ms.carriage.domain.constant.CarriageConstant;
import com.sl.ms.carriage.domain.dto.CarriageDTO;
import com.sl.ms.carriage.domain.dto.WaybillDTO;
import com.sl.ms.carriage.domain.enums.EconomicRegionEnum;
import com.sl.ms.carriage.entity.CarriageEntity;
import com.sl.ms.carriage.enums.CarriageExceptionEnum;
import com.sl.ms.carriage.handler.CarriageChainHandlerFactory;
import com.sl.ms.carriage.mapper.CarriageMapper;
import com.sl.ms.carriage.service.CarriageService;
import com.sl.ms.carriage.utils.CarriageUtils;
import com.sl.transport.common.exception.SLException;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;

/**
 * @Program:sl-express
 * @ClassName:32161
 * @Description:
 * @Author: liSir
 * @CreateDate:2025年5月22日/18:16:01
 * @Version 1.0
 **/
@Service
public class CarriageServiceImpl extends ServiceImpl<CarriageMapper, CarriageEntity> implements CarriageService {
  @Resource
    private AreaFeign areaFeign;
  @Resource
  private CarriageChainHandlerFactory carriageChainHandlerFactory;

  @Override
  public CarriageDTO saveOrUpdate(CarriageDTO carriageDto) {
    //区分
    Integer templateType = carriageDto.getTemplateType();
    Long id = carriageDto.getId();
    if (templateType!= CarriageConstant.ECONOMIC_ZONE)
    {
      CarriageEntity carriageEntity = this.findByTemplateType(templateType);
      if (id==null)
      {
        if (null==carriageEntity)
        {
          this.saveOrUpdate(CarriageUtils.toEntity(carriageDto));
        }else {
          throw new SLException(CarriageExceptionEnum.NOT_ECONOMIC_ZONE_REPEAT);
        }
      }else {
          if (null==carriageEntity)
          {
            throw new SLException(CarriageExceptionEnum.NOT_FOUND);
          }else {
            this.saveOrUpdate(CarriageUtils.toEntity(carriageDto));
          }
       }
      return carriageDto;
    }
   List<CarriageEntity> economicList =this.findByEconomicTemplateType();
    List<String> eoncoset=null;
    economicList.forEach(o->{
      eoncoset.add(o.getAssociatedCity());
    });
    Collection<String> search = CollUtil.intersection(eoncoset, carriageDto.getAssociatedCityList());
    if (CollUtil.isNotEmpty(search)){
      throw new SLException(CarriageExceptionEnum.ECONOMIC_ZONE_CITY_REPEAT);
    }
      this.saveOrUpdate(CarriageUtils.toEntity(carriageDto));
    return carriageDto;
  }

  @Override
  public List<CarriageDTO> findAll() {
    LambdaQueryWrapper<CarriageEntity> wrapper= Wrappers.<CarriageEntity>lambdaQuery().orderByDesc(CarriageEntity::getCreated);
    List<CarriageEntity> list = this.list(wrapper);
    List<CarriageDTO> returnList = new ArrayList<>();
    list.forEach(carriageEntity -> {
        returnList.add(CarriageUtils.toDTO(carriageEntity));
    });
//    list.stream().map(CarriageUtils::toDTO).collect(Collectors.toList());
    return returnList;
  }

  @Override
  public CarriageDTO compute(WaybillDTO waybillDTO) {
//      CarriageEntity carriage =  this.findCarriage(waybillDTO);
      CarriageEntity carriage = carriageChainHandlerFactory.findCarriageEntity(waybillDTO);
      double computeWeight = this.getComputeWeight(waybillDTO, carriage);
      double expense = carriage.getFirstWeight() + ((computeWeight - 1) * carriage.getContinuousWeight());
      expense = NumberUtil.round(expense, 1).doubleValue();

      CarriageDTO carriageDTO = CarriageUtils.toDTO(carriage);
      carriageDTO.setExpense(expense);
      carriageDTO.setComputeWeight(computeWeight);
      return carriageDTO;

  }
    private double getComputeWeight(WaybillDTO waybillDTO, CarriageEntity carriage) {
        Integer volume = waybillDTO.getVolume();
        if (ObjectUtil.isEmpty(volume)){
            try {
                volume = waybillDTO.getMeasureLong() * waybillDTO.getMeasureWidth() * waybillDTO.getMeasureHigh();
            }catch (Exception e)
            {
                volume=0;
            }
        }
        BigDecimal volumeWeight = NumberUtil.div(volume, carriage.getLightThrowingCoefficient(), 1);

        double computeWeight = NumberUtil.max(volumeWeight.doubleValue(), NumberUtil.round(waybillDTO.getWeight(), 1).doubleValue());
        if (computeWeight<=1)
        {
            return 1;
        }
        if (computeWeight<=10)
        {
            return computeWeight;
        }
        if (computeWeight>=100)
        {
            return NumberUtil.round(computeWeight,0).doubleValue();
        }
        int integer = NumberUtil.round(computeWeight, 0, RoundingMode.DOWN).intValue();

        if (NumberUtil.sub(computeWeight, integer) == 0) {
            return integer;
        }

        if (NumberUtil.sub(computeWeight, integer) <= 0.5) {
            return NumberUtil.add(integer, 0.5);
        }
        return NumberUtil.add(integer, 1);
    }

    private CarriageEntity findCarriage(WaybillDTO waybillDTO) {
        if (ObjectUtil.equal(waybillDTO.getReceiverCityId(),waybillDTO.getReceiverCityId()))
        {
            CarriageEntity carriage = this.findByTemplateType(CarriageConstant.SAME_CITY);
            if (ObjectUtil.isNotEmpty(carriage))
            {
                return carriage;
            }
        }
        Long receiverProvinceId = this.areaFeign.get(waybillDTO.getReceiverCityId()).getParentId();
        Long senderProvinceId = this.areaFeign.get(waybillDTO.getSenderCityId()).getParentId();
        if (ObjectUtil.equal(receiverProvinceId, senderProvinceId)) {
            CarriageEntity carriage = this.findByTemplateType(CarriageConstant.SAME_PROVINCE);
            if (ObjectUtil.isNotEmpty(carriage)) {
                return carriage;
            }
        }
  
        CarriageEntity carriage = this.findEconomicCarriage(receiverProvinceId,senderProvinceId);
            if (ObjectUtil.isNotEmpty(carriage)) {
                return carriage;
            }
            carriage= this.findByTemplateType(CarriageConstant.TRANS_PROVINCE);
            if (ObjectUtil.isNotEmpty(carriage)) {
                return carriage;
            }
        throw  new SLException(CarriageExceptionEnum.NOT_FOUND);
    }

    public CarriageEntity findEconomicCarriage(Long receiverProvinceId, Long senderProvinceId) {
        LinkedHashMap<String, EconomicRegionEnum> EnumLinkedHashMap = EnumUtil.getEnumMap(EconomicRegionEnum.class);
        EconomicRegionEnum economicRegionEnum = null;
        for (EconomicRegionEnum regionEnum : EnumLinkedHashMap.values()) {
            //该经济区是否全部包含收发件省id
            boolean result = ArrayUtil.containsAll(regionEnum.getValue(), receiverProvinceId, senderProvinceId);
            if (result) {
                economicRegionEnum = regionEnum;
                break;
            }
        }
        if (economicRegionEnum== null)
        {
            return null;
        }
        LambdaQueryWrapper<CarriageEntity> queryWrapper = Wrappers.lambdaQuery(CarriageEntity.class)
                .eq(CarriageEntity::getTemplateType, CarriageConstant.ECONOMIC_ZONE)
                .eq(CarriageEntity::getTransportType, CarriageConstant.REGULAR_FAST)
                .like(CarriageEntity::getAssociatedCity, economicRegionEnum.getCode());
        return super.getOne(queryWrapper);
    }

    @Override
    public CarriageEntity findByTemplateType(Integer templateType) {
        LambdaQueryWrapper<CarriageEntity> wrapper = Wrappers.<CarriageEntity>lambdaQuery().eq(CarriageEntity::getTemplateType, templateType);
        CarriageEntity carriageEntity = this.getOne(wrapper);
        return carriageEntity;
    }


    public List<CarriageEntity> findByEconomicTemplateType() {
        LambdaQueryWrapper<CarriageEntity> wrapper = Wrappers.<CarriageEntity>lambdaQuery().eq(CarriageEntity::getTemplateType, CarriageConstant.ECONOMIC_ZONE);
        List<CarriageEntity> list = this.list(wrapper);

        return list;
    }



//    @Resource
//    StringRedisTemplate stringRedisTemplate;
//
//    @Override
//    public CarriageDTO saveOrUpdate(CarriageDTO carriageDto) {
//
//        //3. 是否属于经济区互寄模板
//        if (ObjectUtil.notEqual(carriageDto.getTemplateType(), CarriageConstant.ECONOMIC_ZONE)) {
//            //1.根据条件查询模版
//            CarriageEntity carriageEntity = this.findByTemplateType(carriageDto.getTemplateType());
//
//            //2.判断模板是否存在,如果不存在 直接保存
//            if (ObjectUtil.isEmpty(carriageEntity)) {
//                //直接保存
//                return saveOrUpdateDto(carriageDto);
//            }
//            //3.1如果不是经济区,判断id是否为空
//            if (ObjectUtil.isEmpty(carriageDto.getId())) {
//                throw new SLException(CarriageExceptionEnum.NOT_ECONOMIC_ZONE_REPEAT);
//            }
//            //3.2判断当前要修改的id 和已经存在的模版id是否相等
//            if (ObjectUtil.notEqual(carriageDto.getId(), carriageEntity.getId())) {
//                throw new SLException(CarriageExceptionEnum.NOT_ECONOMIC_ZONE_REPEAT);
//            }
//            return saveOrUpdateDto(carriageDto);
//        }
//        //4.是经济区互寄模板，判断新的模板经济区和已存在的模板经济区id不能重复
//        List<CarriageEntity> economicList = findByEconomicTemplateType();
//        //List<String> [4,5]
//        //economicList CarriageEntity 2,3    4,5     ,切割   -->  [2,3,4,5]
//        List<String> associatedCityList = economicList.stream()
//                .map(CarriageEntity::getAssociatedCity)//2,3   4,5
//                .map(associatedCityStr -> StrUtil.split(associatedCityStr, ","))
//                .flatMap(StreamUtil::of)
//                .collect(Collectors.toList());
//        Collection<String> intersection = CollUtil.intersection(associatedCityList, carriageDto.getAssociatedCityList());
//        if (CollUtil.isNotEmpty(intersection)) {
//            throw new SLException(CarriageExceptionEnum.NOT_ECONOMIC_ZONE_REPEAT);
//        }
//        return saveOrUpdateDto(carriageDto);
//    }
//
//    @NotNull
//    private CarriageDTO saveOrUpdateDto(CarriageDTO carriageDto) {
//        CarriageEntity entity = CarriageUtils.toEntity(carriageDto);
//        this.saveOrUpdate(entity);
//        return CarriageUtils.toDTO(entity);
//    }
//    @Override
//    public List<CarriageDTO> findAll() {
//        //根据创建时间降序排序
//        LambdaQueryWrapper<CarriageEntity> queryWrapper = Wrappers.<CarriageEntity>lambdaQuery().orderByDesc(CarriageEntity::getCreated);
//        List<CarriageEntity> list = this.list(queryWrapper);
//        stringRedisTemplate.opsForValue().set("list", JSON.toJSONString(list));//存入缓存
//        return list.stream().map(CarriageUtils::toDTO).collect(Collectors.toList());
//    }
//    @Resource
//    CarriageChainHandler carriageChainHandler;
//    @Override
//    public CarriageDTO compute(WaybillDTO waybillDTO) {
//        //1.查询运费模板
////        CarriageEntity carriageEntity = findCarriageTemplate(waybillDTO);
////        CarriageEntity carriageEntity = carriageChainHandler.findCarriage(waybillDTO);
//       CarriageEntity carriageEntity = carriageChainHandler.findCarriage(waybillDTO);
//        //2.算出计算重量
//        double weight = computeweight(waybillDTO,carriageEntity);
//
//        //3.根据公式计算运费 运费 = 首重价格 + 续重价格 * （计费重量-1）
//        double expense = carriageEntity.getFirstWeight() + carriageEntity.getContinuousWeight() * (weight - 1);
//        expense = NumberUtil.round(expense,1).doubleValue();
//        CarriageDTO carriageDTO = CarriageUtils.toDTO(carriageEntity);
//        carriageDTO.setExpense(expense);
//        return carriageDTO;
//    }
//
//    private double computeweight(WaybillDTO waybillDTO,CarriageEntity carriageEntity) {
//        //1.查询体积
//        Integer volume = waybillDTO.getVolume();
//        if (ObjectUtil.isEmpty(volume)) {
//            Integer measureLong = waybillDTO.getMeasureLong();
//            Integer measureWidth = waybillDTO.getMeasureWidth();
//            Integer measureHigh = waybillDTO.getMeasureHigh();
//            try {
//                volume = measureLong * measureHigh * measureWidth;
//            } catch (Exception e) {
//                volume = 0;
//            }
//        }
//        //2.体积重量 = 体积 / 轻抛系数
//        BigDecimal volumeWight = NumberUtil.div(volume, carriageEntity.getContinuousWeight());
//        //3.可对比实际重量 和 体积重量 最大值
//        double computeWeight = NumberUtil.max(volumeWight.doubleValue(), waybillDTO.getWeight());
//        //4.按照需求优化小数点
//        //不满1kg, 按1kg计费:
//        if(computeWeight<1){
//            return 1;
//        }
//        //10kg以下,以0.1kg为计重单位,四舍五入保留1位小数:
//        if(computeWeight<=10){
//            return NumberUtil.round(computeWeight,1).doubleValue();
//        }
//        //100KG及以上,四舍五入取整
//        if(computeWeight>=100){
//            return NumberUtil.round(computeWeight,0).doubleValue();
//        }
//        //10-100kg:续重以0.5kg为计重单位，不足0.5kg按0.5kg算，四舍五入保留1位小数:
//        //18.1 ---> 18.5   18
//        //18.6 ---> 19
//        double round = NumberUtil.round(computeWeight, 0, RoundingMode.DOWN).doubleValue();
//        double sub = computeWeight - round;
//        if(sub<0.5){
//            return NumberUtil.add(round,0.5);
//        }else{
//            return NumberUtil.add(round,1);
//        }
//    }
//
//    @Resource
//    private AreaFeign areaFeign;
//
//    private CarriageEntity findCarriageTemplate(WaybillDTO waybillDTO) {
//        //找模板的顺序:同城模板 -->同省 -->经济区 --> 跨省
//        //1.找同城模板
//        Long senderCityId = waybillDTO.getSenderCityId();
//        Long receiverCityId = waybillDTO.getReceiverCityId();
//
//        if (ObjectUtil.equals(senderCityId, receiverCityId)) {
//            CarriageEntity carriageEntity = findByTemplateType(CarriageConstant.SAME_CITY);
//            if (ObjectUtil.isNotEmpty(carriageEntity)) {
//                return carriageEntity;
//            }
//        }
//        //2.找同省模板
//        Long senderProvinceId = areaFeign.get(senderCityId).getParentId();
//        Long receiverProvinceId = areaFeign.get(receiverCityId).getParentId();
//        if (ObjectUtil.equals(senderProvinceId, receiverProvinceId)) {
//            CarriageEntity carriageEntity = findByTemplateType(CarriageConstant.SAME_PROVINCE);
//            if (ObjectUtil.isNotEmpty(carriageEntity)) {
//                return carriageEntity;
//            }
//        }
//
//        //3.经济区互寄
//        CarriageEntity carriageEntity = findByEconomic(senderProvinceId, receiverProvinceId);
//        if (ObjectUtil.isNotEmpty(carriageEntity)) {
//            return carriageEntity;
//        }
//
//        //4.跨省
//        carriageEntity = findByTemplateType(CarriageConstant.TRANS_PROVINCE);
//        if (ObjectUtil.isNotEmpty(carriageEntity)) {
//            return carriageEntity;
//        }
//
//        throw new SLException(CarriageExceptionEnum.NOT_FOUND);
//    }
//
//    private CarriageEntity findByEconomic(Long senderProvinceId, Long receiverProvinceId) {
//        LinkedHashMap<String, EconomicRegionEnum> enumMap = EnumUtil.getEnumMap(EconomicRegionEnum.class);
//        EconomicRegionEnum economicRegionEnum = null;
//
//
//        for (EconomicRegionEnum regionEnum : enumMap.values()) {
//            Long[] value = regionEnum.getValue();
//            boolean containsAll = ArrayUtil.containsAll(value, senderProvinceId, receiverProvinceId);
//            if (containsAll) {
//                economicRegionEnum = regionEnum;
//                break;
//            }
//        }
//
//        if (ObjectUtil.isNull(economicRegionEnum)) {
//            return null;
//        }
//
//        CarriageEntity carriageEntity = this.getOne(Wrappers.<CarriageEntity>lambdaQuery()
//                .eq(CarriageEntity::getTemplateType, CarriageConstant.ECONOMIC_ZONE)
//                .like(CarriageEntity::getAssociatedCity, economicRegionEnum.getCode())
//        );
//        return carriageEntity;
//    }
//
//
//    public List<CarriageEntity> findByEconomicTemplateType() {
//        LambdaQueryWrapper<CarriageEntity> queryWrapper = Wrappers.<CarriageEntity>lambdaQuery()
//                .eq(CarriageEntity::getTemplateType, CarriageConstant.ECONOMIC_ZONE);
//        return this.list(queryWrapper);
//    }
//
//    @Override
//    public CarriageEntity findByTemplateType(Integer templateType) {
//        if (ObjectUtil.equals(CarriageConstant.ECONOMIC_ZONE, templateType)) {
//            throw new SLException(CarriageExceptionEnum.TEMPLATE_TYPE_NOT_SUPPORT);
//        }
//
//        LambdaQueryWrapper<CarriageEntity> queryWrapper = Wrappers.<CarriageEntity>lambdaQuery().eq
//                (CarriageEntity::getTemplateType, templateType);
//        CarriageEntity carriageEntity = this.getOne(queryWrapper);
//        return carriageEntity;
//    }
}
